/*
 * Copyright (C) 2016 Lokiy(liulongke@gmail.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *  　　　　http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

@file:Suppress("unused")

package com.lokiy.core.adapter

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import com.lokiy.core.R

/**
 * BasicAdapter
 * lokiy
 * 2021-01-27
 */
@Deprecated(replaceWith = ReplaceWith(""), message = "")
abstract class BasicAdapter<T>(
    private val pageSize: Int = 20,
    private val onLoadMoreListener: (BasicAdapter<T>.() -> Unit)?
) : RecyclerView.Adapter<BasicAdapter.Holder<T?>>(), IEmptyItemDecoration {

    /**
     * 数据对象
     */
    private val _data: MutableList<T> = ArrayList()
    protected val data: List<T>
        get() = ArrayList(_data)

    /**
     * 是否是正在加载中
     */
    var isOnLoadMore = false

    /**
     * 是否是加载完成 用于展示footer
     */
    var isEnd = false
        private set
    private var recyclerView: RecyclerView? = null

    final override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder<T?> {
        return if (viewType == R.layout.item_footer) {
            FooterHolder(LayoutInflater.from(parent.context).inflate(R.layout.item_footer, parent, false))
        } else {
            onCreateViewHolder1(parent, viewType)
        }
    }

    abstract fun onCreateViewHolder1(parent: ViewGroup, viewType: Int): Holder<T?>

    override fun onBindViewHolder(holder: Holder<T?>, position: Int) = holder.bindData(getItem(position))

    protected open fun getItem(position: Int): T? = _data.getOrNull(position)

    final override fun getItemViewType(position: Int): Int {
        if (position >= _data.size - 2 && !isOnLoadMore && !isEnd) {
            isOnLoadMore = true
            onLoadMoreListener?.invoke(this)
        }
        return if (hasFooter() && position == itemCount - 1) R.layout.item_footer else getItemViewType1(position)
    }

    /**
     * Return the view type of the item at <code>position</code> for the purposes
     * of view recycling.
     *
     * <p>The default implementation of this method returns 0, making the assumption of
     * a single view type for the adapter. Unlike ListView adapters, types need not
     * be contiguous. Consider using id resources to uniquely identify item view types.
     *
     * @param position position to query
     * @return integer value identifying the type of the view needed to represent the item at
     *                 <code>position</code>. Type codes need not be contiguous.
     */
    protected abstract fun getItemViewType1(position: Int): Int

    /**
     * 是否需要加载中的状态
     * @see isOnLoadMore
     * @see isEnd
     */
    open fun hasFooter() = false

    override fun getItemCount(): Int = _data.size + if (hasFooter() && _data.isNotEmpty()) 1 else 0

    override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
        this.recyclerView = recyclerView
        super<IEmptyItemDecoration>.onAttachedToRecyclerView(recyclerView)
    }

    override fun onDetachedFromRecyclerView(recyclerView: RecyclerView) = super<IEmptyItemDecoration>.onDetachedFromRecyclerView(recyclerView)

    /**
     * 附加数据
     */
    fun addAll(data: List<T>?) {
        data ?: return
        isOnLoadMore = false
        if (data.size < pageSize) {
            isEnd = true
        }
        val itemCount = itemCount
        this._data.addAll(data)
        notifyItemRangeInserted(itemCount, data.size)
    }

    /**
     * 刷新列表 更新数据
     * 确认两个item是否是同一个item是判断 item.hashCode()是否一致 如果一致就判定为同一个item
     * 然后会去判断item内容是否相同 可以重写 [Object.equals] 方法 来判断item是否有改变
     */
    fun refresh(data: List<T>?, isNotify: Boolean = true) {
        isOnLoadMore = false
        isEnd = false
        val newData = data ?: ArrayList()
        if (newData.size < pageSize) {
            isEnd = true
        }
        val lastData = ArrayList(this._data)
        this._data.clear()
        this._data.addAll(newData)
        if (isNotify) {
            if (newData.isEmpty() && (hasFooter() || itemCount > 0)) {
                notifyDataSetChanged()
            } else {
                DiffUtil.calculateDiff(object : DiffUtil.Callback() {

                    override fun getOldListSize(): Int = lastData.size

                    override fun getNewListSize(): Int = newData.size

                    override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean =
                        lastData.getOrNull(oldItemPosition)?.hashCode() == newData.getOrNull(newItemPosition)?.hashCode()

                    override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean =
                        lastData.getOrNull(oldItemPosition) == newData.getOrNull(newItemPosition)

                }).dispatchUpdatesTo(this)
            }
        }
        if (newData.isEmpty()) {
            addOrRemoveEmptyHeaderDecor(recyclerView ?: return)
        } else {
            if (lastData.firstOrNull() != newData.firstOrNull()) {
                recyclerView?.postDelayed({
                    recyclerView?.smoothScrollToPosition(0)
                }, 100)
            }
        }
    }

    /**
     * 移除item
     *
     * @param t t
     */
    fun remove(t: T) {
        val index = _data.indexOf(t)
        if (index >= 0) {
            if (_data.remove(t)) {
                notifyItemRemoved(index)
            }
        }
    }

    /**
     * Holder
     *
     * @param <T>
     */
    public abstract class Holder<T>(itemView: View) : RecyclerView.ViewHolder(itemView) {
        public abstract fun bindData(data: T?)
    }

    /**
     *
     * Footer Holder
     * 包含加载中状态等
     */
    private inner class FooterHolder(itemView: View) : Holder<T?>(itemView) {
        private val progressView: View = itemView.findViewById(R.id.progress_bar)
        private val loadingTips: TextView = itemView.findViewById(R.id.loading_tips)

        override fun bindData(data: T?) {
            progressView.visibility = if (isOnLoadMore && !isEnd) View.VISIBLE else View.GONE
            loadingTips.text = itemView.context.getString(
                when {
                    isEnd -> R.string.lokiy_load_complete
                    isOnLoadMore -> R.string.lokiy_loading
                    else -> R.string.lokiy_load_end
                }
            )
        }
    }

}